| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/cancelable_callback.h" | 5 #include "base/cancelable_callback.h" |
| 6 #include "base/command_line.h" | 6 #include "base/command_line.h" |
| 7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
| 9 #include "base/strings/stringprintf.h" |
| 9 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
| 10 #include "base/test/simple_test_clock.h" | 11 #include "base/test/simple_test_clock.h" |
| 11 #include "chrome/browser/extensions/activity_log/activity_log.h" | 12 #include "chrome/browser/extensions/activity_log/activity_log.h" |
| 12 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h" | 13 #include "chrome/browser/extensions/activity_log/counting_policy.h" |
| 13 #include "chrome/browser/extensions/extension_service.h" | 14 #include "chrome/browser/extensions/extension_service.h" |
| 14 #include "chrome/browser/extensions/test_extension_system.h" | 15 #include "chrome/browser/extensions/test_extension_system.h" |
| 15 #include "chrome/common/chrome_constants.h" | 16 #include "chrome/common/chrome_constants.h" |
| 16 #include "chrome/common/chrome_switches.h" | 17 #include "chrome/common/chrome_switches.h" |
| 17 #include "chrome/common/extensions/extension_builder.h" | 18 #include "chrome/common/extensions/extension_builder.h" |
| 18 #include "chrome/test/base/chrome_render_view_host_test_harness.h" | 19 #include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| 19 #include "chrome/test/base/testing_profile.h" | 20 #include "chrome/test/base/testing_profile.h" |
| 20 #include "content/public/test/test_browser_thread_bundle.h" | 21 #include "content/public/test/test_browser_thread_bundle.h" |
| 21 #include "sql/statement.h" | 22 #include "sql/statement.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 24 |
| 24 #if defined(OS_CHROMEOS) | 25 #if defined(OS_CHROMEOS) |
| 25 #include "chrome/browser/chromeos/login/user_manager.h" | 26 #include "chrome/browser/chromeos/login/user_manager.h" |
| 26 #include "chrome/browser/chromeos/settings/cros_settings.h" | 27 #include "chrome/browser/chromeos/settings/cros_settings.h" |
| 27 #include "chrome/browser/chromeos/settings/device_settings_service.h" | 28 #include "chrome/browser/chromeos/settings/device_settings_service.h" |
| 28 #endif | 29 #endif |
| 29 | 30 |
| 30 namespace extensions { | 31 namespace extensions { |
| 31 | 32 |
| 32 class FullStreamUIPolicyTest : public testing::Test { | 33 class CountingPolicyTest : public testing::Test { |
| 33 public: | 34 public: |
| 34 FullStreamUIPolicyTest() | 35 CountingPolicyTest() |
| 35 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), | 36 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), |
| 36 saved_cmdline_(CommandLine::NO_PROGRAM) { | 37 saved_cmdline_(CommandLine::NO_PROGRAM) { |
| 37 #if defined OS_CHROMEOS | 38 #if defined OS_CHROMEOS |
| 38 test_user_manager_.reset(new chromeos::ScopedTestUserManager()); | 39 test_user_manager_.reset(new chromeos::ScopedTestUserManager()); |
| 39 #endif | 40 #endif |
| 40 CommandLine command_line(CommandLine::NO_PROGRAM); | 41 CommandLine command_line(CommandLine::NO_PROGRAM); |
| 41 saved_cmdline_ = *CommandLine::ForCurrentProcess(); | 42 saved_cmdline_ = *CommandLine::ForCurrentProcess(); |
| 42 profile_.reset(new TestingProfile()); | 43 profile_.reset(new TestingProfile()); |
| 43 CommandLine::ForCurrentProcess()->AppendSwitch( | 44 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 44 switches::kEnableExtensionActivityLogging); | 45 switches::kEnableExtensionActivityLogging); |
| 45 CommandLine::ForCurrentProcess()->AppendSwitch( | 46 CommandLine::ForCurrentProcess()->AppendSwitch( |
| 46 switches::kEnableExtensionActivityLogTesting); | 47 switches::kEnableExtensionActivityLogTesting); |
| 47 extension_service_ = static_cast<TestExtensionSystem*>( | 48 extension_service_ = static_cast<TestExtensionSystem*>( |
| 48 ExtensionSystem::Get(profile_.get()))->CreateExtensionService | 49 ExtensionSystem::Get(profile_.get()))->CreateExtensionService |
| 49 (&command_line, base::FilePath(), false); | 50 (&command_line, base::FilePath(), false); |
| 50 } | 51 } |
| 51 | 52 |
| 52 virtual ~FullStreamUIPolicyTest() { | 53 virtual ~CountingPolicyTest() { |
| 53 #if defined OS_CHROMEOS | 54 #if defined OS_CHROMEOS |
| 54 test_user_manager_.reset(); | 55 test_user_manager_.reset(); |
| 55 #endif | 56 #endif |
| 56 base::RunLoop().RunUntilIdle(); | 57 base::RunLoop().RunUntilIdle(); |
| 57 profile_.reset(NULL); | 58 profile_.reset(NULL); |
| 58 base::RunLoop().RunUntilIdle(); | 59 base::RunLoop().RunUntilIdle(); |
| 59 // Restore the original command line and undo the affects of SetUp(). | 60 // Restore the original command line and undo the affects of SetUp(). |
| 60 *CommandLine::ForCurrentProcess() = saved_cmdline_; | 61 *CommandLine::ForCurrentProcess() = saved_cmdline_; |
| 61 } | 62 } |
| 62 | 63 |
| 63 // A helper function to call ReadData on a policy object and wait for the | 64 // A helper function to call ReadData on a policy object and wait for the |
| 64 // results to be processed. | 65 // results to be processed. |
| 65 void CheckReadData( | 66 void CheckReadData( |
| 66 ActivityLogPolicy* policy, | 67 ActivityLogPolicy* policy, |
| 67 const std::string& extension_id, | 68 const std::string& extension_id, |
| 68 const int day, | 69 const int day, |
| 69 const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker) { | 70 const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker) { |
| 70 // Submit a request to the policy to read back some data, and call the | 71 // Submit a request to the policy to read back some data, and call the |
| 71 // checker function when results are available. This will happen on the | 72 // checker function when results are available. This will happen on the |
| 72 // database thread. | 73 // database thread. |
| 73 policy->ReadData( | 74 policy->ReadData( |
| 74 extension_id, | 75 extension_id, |
| 75 day, | 76 day, |
| 76 base::Bind(&FullStreamUIPolicyTest::CheckWrapper, | 77 base::Bind(&CountingPolicyTest::CheckWrapper, |
| 77 checker, | 78 checker, |
| 78 base::MessageLoop::current()->QuitClosure())); | 79 base::MessageLoop::current()->QuitClosure())); |
| 79 | 80 |
| 80 // Set up a timeout that will trigger after 5 seconds; if we haven't | 81 // Set up a timeout that will trigger after 5 seconds; if we haven't |
| 81 // received any results by then assume that the test is broken. | 82 // received any results by then assume that the test is broken. |
| 82 base::CancelableClosure timeout( | 83 base::CancelableClosure timeout( |
| 83 base::Bind(&FullStreamUIPolicyTest::TimeoutCallback)); | 84 base::Bind(&CountingPolicyTest::TimeoutCallback)); |
| 84 base::MessageLoop::current()->PostDelayedTask( | 85 base::MessageLoop::current()->PostDelayedTask( |
| 85 FROM_HERE, timeout.callback(), base::TimeDelta::FromSeconds(5)); | 86 FROM_HERE, timeout.callback(), base::TimeDelta::FromSeconds(5)); |
| 86 | 87 |
| 87 // Wait for results; either the checker or the timeout callbacks should | 88 // Wait for results; either the checker or the timeout callbacks should |
| 88 // cause the main loop to exit. | 89 // cause the main loop to exit. |
| 89 base::MessageLoop::current()->Run(); | 90 base::MessageLoop::current()->Run(); |
| 90 | 91 |
| 91 timeout.Cancel(); | 92 timeout.Cancel(); |
| 92 } | 93 } |
| 93 | 94 |
| 94 static void CheckWrapper( | 95 static void CheckWrapper( |
| 95 const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker, | 96 const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker, |
| 96 const base::Closure& done, | 97 const base::Closure& done, |
| 97 scoped_ptr<Action::ActionVector> results) { | 98 scoped_ptr<Action::ActionVector> results) { |
| 98 checker.Run(results.Pass()); | 99 checker.Run(results.Pass()); |
| 99 done.Run(); | 100 done.Run(); |
| 100 } | 101 } |
| 101 | 102 |
| 102 static void TimeoutCallback() { | 103 static void TimeoutCallback() { |
| 103 base::MessageLoop::current()->QuitWhenIdle(); | 104 base::MessageLoop::current()->QuitWhenIdle(); |
| 104 FAIL() << "Policy test timed out waiting for results"; | 105 FAIL() << "Policy test timed out waiting for results"; |
| 105 } | 106 } |
| 106 | 107 |
| 107 static void RetrieveActions_LogAndFetchActions( | 108 static void Arguments_Stripped(scoped_ptr<Action::ActionVector> i) { |
| 108 scoped_ptr<std::vector<scoped_refptr<Action> > > i) { | |
| 109 ASSERT_EQ(2, static_cast<int>(i->size())); | |
| 110 } | |
| 111 | |
| 112 static void Arguments_Present(scoped_ptr<Action::ActionVector> i) { | |
| 113 scoped_refptr<Action> last = i->front(); | 109 scoped_refptr<Action> last = i->front(); |
| 114 std::string args = | 110 std::string args = |
| 115 "ID=odlameecjipmbmbejkplpemijjgpljce CATEGORY=api_call " | 111 "ID=odlameecjipmbmbejkplpemijjgpljce CATEGORY=api_call " |
| 116 "API=extension.connect ARGS=[\"hello\",\"world\"]"; | 112 "API=extension.connect ARGS=[\"hello\",\"world\"] COUNT=1"; |
| 117 ASSERT_EQ(args, last->PrintForDebug()); | 113 ASSERT_EQ(args, last->PrintForDebug()); |
| 118 } | 114 } |
| 119 | 115 |
| 120 static void Arguments_GetTodaysActions( | 116 static void Arguments_GetTodaysActions( |
| 121 scoped_ptr<Action::ActionVector> actions) { | 117 scoped_ptr<Action::ActionVector> actions) { |
| 118 std::string api_stripped_print = |
| 119 "ID=punky CATEGORY=api_call API=brewster COUNT=2"; |
| 122 std::string api_print = | 120 std::string api_print = |
| 123 "ID=punky CATEGORY=api_call API=brewster ARGS=[\"woof\"]"; | 121 "ID=punky CATEGORY=api_call API=extension.sendMessage " |
| 122 "ARGS=[\"not\",\"stripped\"] COUNT=1"; |
| 124 std::string dom_print = | 123 std::string dom_print = |
| 125 "ID=punky CATEGORY=dom_access API=lets ARGS=[\"vamoose\"] " | 124 "ID=punky CATEGORY=dom_access API=lets ARGS=[\"vamoose\"] " |
| 126 "PAGE_URL=http://www.google.com/"; | 125 "PAGE_URL=http://www.google.com/ COUNT=1"; |
| 126 ASSERT_EQ(3, static_cast<int>(actions->size())); |
| 127 ASSERT_EQ(dom_print, actions->at(0)->PrintForDebug()); |
| 128 ASSERT_EQ(api_print, actions->at(1)->PrintForDebug()); |
| 129 ASSERT_EQ(api_stripped_print, actions->at(2)->PrintForDebug()); |
| 130 } |
| 131 |
| 132 static void Arguments_GetOlderActions( |
| 133 scoped_ptr<Action::ActionVector> actions) { |
| 134 std::string api_print = |
| 135 "ID=punky CATEGORY=api_call API=brewster COUNT=1"; |
| 136 std::string dom_print = |
| 137 "ID=punky CATEGORY=dom_access API=lets ARGS=[\"vamoose\"] " |
| 138 "PAGE_URL=http://www.google.com/ COUNT=1"; |
| 127 ASSERT_EQ(2, static_cast<int>(actions->size())); | 139 ASSERT_EQ(2, static_cast<int>(actions->size())); |
| 128 ASSERT_EQ(dom_print, actions->at(0)->PrintForDebug()); | 140 ASSERT_EQ(dom_print, actions->at(0)->PrintForDebug()); |
| 129 ASSERT_EQ(api_print, actions->at(1)->PrintForDebug()); | 141 ASSERT_EQ(api_print, actions->at(1)->PrintForDebug()); |
| 130 } | 142 } |
| 131 | 143 |
| 132 static void Arguments_GetOlderActions( | 144 static void Arguments_CheckMergeCount( |
| 145 int count, |
| 133 scoped_ptr<Action::ActionVector> actions) { | 146 scoped_ptr<Action::ActionVector> actions) { |
| 134 std::string api_print = | 147 std::string api_print = base::StringPrintf( |
| 135 "ID=punky CATEGORY=api_call API=brewster ARGS=[\"woof\"]"; | 148 "ID=punky CATEGORY=api_call API=brewster COUNT=%d", count); |
| 136 std::string dom_print = | 149 if (count > 0) { |
| 137 "ID=punky CATEGORY=dom_access API=lets ARGS=[\"vamoose\"] " | 150 ASSERT_EQ(1u, actions->size()); |
| 138 "PAGE_URL=http://www.google.com/"; | 151 ASSERT_EQ(api_print, actions->at(0)->PrintForDebug()); |
| 139 ASSERT_EQ(2, static_cast<int>(actions->size())); | 152 } else { |
| 140 ASSERT_EQ(dom_print, actions->at(0)->PrintForDebug()); | 153 ASSERT_EQ(0u, actions->size()); |
| 141 ASSERT_EQ(api_print, actions->at(1)->PrintForDebug()); | 154 } |
| 142 } | 155 } |
| 143 | 156 |
| 144 protected: | 157 protected: |
| 145 ExtensionService* extension_service_; | 158 ExtensionService* extension_service_; |
| 146 scoped_ptr<TestingProfile> profile_; | 159 scoped_ptr<TestingProfile> profile_; |
| 147 content::TestBrowserThreadBundle thread_bundle_; | 160 content::TestBrowserThreadBundle thread_bundle_; |
| 148 // Used to preserve a copy of the original command line. | 161 // Used to preserve a copy of the original command line. |
| 149 // The test framework will do this itself as well. However, by then, | 162 // The test framework will do this itself as well. However, by then, |
| 150 // it is too late to call ActivityLog::RecomputeLoggingIsEnabled() in | 163 // it is too late to call ActivityLog::RecomputeLoggingIsEnabled() in |
| 151 // TearDown(). | 164 // TearDown(). |
| 152 CommandLine saved_cmdline_; | 165 CommandLine saved_cmdline_; |
| 153 | 166 |
| 154 #if defined OS_CHROMEOS | 167 #if defined OS_CHROMEOS |
| 155 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; | 168 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; |
| 156 chromeos::ScopedTestCrosSettings test_cros_settings_; | 169 chromeos::ScopedTestCrosSettings test_cros_settings_; |
| 157 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_; | 170 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_; |
| 158 #endif | 171 #endif |
| 159 }; | 172 }; |
| 160 | 173 |
| 161 TEST_F(FullStreamUIPolicyTest, Construct) { | 174 TEST_F(CountingPolicyTest, Construct) { |
| 162 ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get()); | 175 ActivityLogPolicy* policy = new CountingPolicy(profile_.get()); |
| 163 scoped_refptr<const Extension> extension = | 176 scoped_refptr<const Extension> extension = |
| 164 ExtensionBuilder() | 177 ExtensionBuilder() |
| 165 .SetManifest(DictionaryBuilder() | 178 .SetManifest(DictionaryBuilder() |
| 166 .Set("name", "Test extension") | 179 .Set("name", "Test extension") |
| 167 .Set("version", "1.0.0") | 180 .Set("version", "1.0.0") |
| 168 .Set("manifest_version", 2)) | 181 .Set("manifest_version", 2)) |
| 169 .Build(); | 182 .Build(); |
| 170 extension_service_->AddExtension(extension.get()); | 183 extension_service_->AddExtension(extension.get()); |
| 171 scoped_ptr<base::ListValue> args(new base::ListValue()); | 184 scoped_ptr<base::ListValue> args(new base::ListValue()); |
| 172 scoped_refptr<Action> action = new Action(extension->id(), | 185 scoped_refptr<Action> action = new Action(extension->id(), |
| 173 base::Time::Now(), | 186 base::Time::Now(), |
| 174 Action::ACTION_API_CALL, | 187 Action::ACTION_API_CALL, |
| 175 "tabs.testMethod"); | 188 "tabs.testMethod"); |
| 176 action->set_args(args.Pass()); | 189 action->set_args(args.Pass()); |
| 177 policy->ProcessAction(action); | 190 policy->ProcessAction(action); |
| 178 policy->Close(); | 191 policy->Close(); |
| 179 } | 192 } |
| 180 | 193 |
| 181 TEST_F(FullStreamUIPolicyTest, LogAndFetchActions) { | 194 TEST_F(CountingPolicyTest, LogWithStrippedArguments) { |
| 182 ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get()); | 195 ActivityLogPolicy* policy = new CountingPolicy(profile_.get()); |
| 183 scoped_refptr<const Extension> extension = | 196 scoped_refptr<const Extension> extension = |
| 184 ExtensionBuilder() | 197 ExtensionBuilder() |
| 185 .SetManifest(DictionaryBuilder() | 198 .SetManifest(DictionaryBuilder() |
| 186 .Set("name", "Test extension") | |
| 187 .Set("version", "1.0.0") | |
| 188 .Set("manifest_version", 2)) | |
| 189 .Build(); | |
| 190 extension_service_->AddExtension(extension.get()); | |
| 191 GURL gurl("http://www.google.com"); | |
| 192 | |
| 193 // Write some API calls | |
| 194 scoped_refptr<Action> action_api = new Action(extension->id(), | |
| 195 base::Time::Now(), | |
| 196 Action::ACTION_API_CALL, | |
| 197 "tabs.testMethod"); | |
| 198 action_api->set_args(make_scoped_ptr(new base::ListValue())); | |
| 199 policy->ProcessAction(action_api); | |
| 200 | |
| 201 scoped_refptr<Action> action_dom = new Action(extension->id(), | |
| 202 base::Time::Now(), | |
| 203 Action::ACTION_DOM_ACCESS, | |
| 204 "document.write"); | |
| 205 action_dom->set_args(make_scoped_ptr(new base::ListValue())); | |
| 206 action_dom->set_page_url(gurl); | |
| 207 policy->ProcessAction(action_dom); | |
| 208 | |
| 209 CheckReadData( | |
| 210 policy, | |
| 211 extension->id(), | |
| 212 0, | |
| 213 base::Bind(&FullStreamUIPolicyTest::RetrieveActions_LogAndFetchActions)); | |
| 214 | |
| 215 policy->Close(); | |
| 216 } | |
| 217 | |
| 218 TEST_F(FullStreamUIPolicyTest, LogWithArguments) { | |
| 219 ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get()); | |
| 220 scoped_refptr<const Extension> extension = | |
| 221 ExtensionBuilder() | |
| 222 .SetManifest(DictionaryBuilder() | |
| 223 .Set("name", "Test extension") | 199 .Set("name", "Test extension") |
| 224 .Set("version", "1.0.0") | 200 .Set("version", "1.0.0") |
| 225 .Set("manifest_version", 2)) | 201 .Set("manifest_version", 2)) |
| 226 .Build(); | 202 .Build(); |
| 227 extension_service_->AddExtension(extension.get()); | 203 extension_service_->AddExtension(extension.get()); |
| 228 | 204 |
| 229 scoped_ptr<base::ListValue> args(new base::ListValue()); | 205 scoped_ptr<base::ListValue> args(new base::ListValue()); |
| 230 args->Set(0, new base::StringValue("hello")); | 206 args->Set(0, new base::StringValue("hello")); |
| 231 args->Set(1, new base::StringValue("world")); | 207 args->Set(1, new base::StringValue("world")); |
| 232 scoped_refptr<Action> action = new Action(extension->id(), | 208 scoped_refptr<Action> action = new Action(extension->id(), |
| 233 base::Time::Now(), | 209 base::Time::Now(), |
| 234 Action::ACTION_API_CALL, | 210 Action::ACTION_API_CALL, |
| 235 "extension.connect"); | 211 "extension.connect"); |
| 236 action->set_args(args.Pass()); | 212 action->set_args(args.Pass()); |
| 237 | 213 |
| 238 policy->ProcessAction(action); | 214 policy->ProcessAction(action); |
| 239 CheckReadData(policy, | 215 CheckReadData(policy, |
| 240 extension->id(), | 216 extension->id(), |
| 241 0, | 217 0, |
| 242 base::Bind(&FullStreamUIPolicyTest::Arguments_Present)); | 218 base::Bind(&CountingPolicyTest::Arguments_Stripped)); |
| 243 policy->Close(); | 219 policy->Close(); |
| 244 } | 220 } |
| 245 | 221 |
| 246 TEST_F(FullStreamUIPolicyTest, GetTodaysActions) { | 222 TEST_F(CountingPolicyTest, GetTodaysActions) { |
| 247 ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get()); | 223 CountingPolicy* policy = new CountingPolicy(profile_.get()); |
| 224 // Disable row expiration for this test by setting a time before any actions |
| 225 // we generate. |
| 226 policy->set_retention_time(base::TimeDelta::FromDays(14)); |
| 248 | 227 |
| 249 // Use a mock clock to ensure that events are not recorded on the wrong day | 228 // Use a mock clock to ensure that events are not recorded on the wrong day |
| 250 // when the test is run close to local midnight. | 229 // when the test is run close to local midnight. Note: Ownership is passed |
| 251 base::SimpleTestClock mock_clock; | 230 // to the policy, but we still keep a pointer locally. The policy will take |
| 252 mock_clock.SetNow(base::Time::Now().LocalMidnight() + | 231 // care of destruction; this is safe since the policy outlives all our |
| 253 base::TimeDelta::FromHours(12)); | 232 // accesses to the mock clock. |
| 254 policy->SetClockForTesting(&mock_clock); | 233 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); |
| 234 mock_clock->SetNow(base::Time::Now().LocalMidnight() + |
| 235 base::TimeDelta::FromHours(12)); |
| 236 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); |
| 255 | 237 |
| 256 // Record some actions | 238 // Record some actions |
| 257 scoped_refptr<Action> action = | 239 scoped_refptr<Action> action = |
| 258 new Action("punky", | 240 new Action("punky", |
| 259 mock_clock.Now() - base::TimeDelta::FromMinutes(40), | 241 mock_clock->Now() - base::TimeDelta::FromMinutes(40), |
| 260 Action::ACTION_API_CALL, | 242 Action::ACTION_API_CALL, |
| 261 "brewster"); | 243 "brewster"); |
| 262 action->mutable_args()->AppendString("woof"); | 244 action->mutable_args()->AppendString("woof"); |
| 263 policy->ProcessAction(action); | 245 policy->ProcessAction(action); |
| 264 | 246 |
| 247 action = new Action("punky", |
| 248 mock_clock->Now() - base::TimeDelta::FromMinutes(30), |
| 249 Action::ACTION_API_CALL, |
| 250 "brewster"); |
| 251 action->mutable_args()->AppendString("meow"); |
| 252 policy->ProcessAction(action); |
| 253 |
| 254 action = new Action("punky", |
| 255 mock_clock->Now() - base::TimeDelta::FromMinutes(20), |
| 256 Action::ACTION_API_CALL, |
| 257 "extension.sendMessage"); |
| 258 action->mutable_args()->AppendString("not"); |
| 259 action->mutable_args()->AppendString("stripped"); |
| 260 policy->ProcessAction(action); |
| 261 |
| 265 action = | 262 action = |
| 266 new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets"); | 263 new Action("punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); |
| 267 action->mutable_args()->AppendString("vamoose"); | 264 action->mutable_args()->AppendString("vamoose"); |
| 268 action->set_page_url(GURL("http://www.google.com")); | 265 action->set_page_url(GURL("http://www.google.com")); |
| 269 policy->ProcessAction(action); | 266 policy->ProcessAction(action); |
| 270 | 267 |
| 271 action = new Action( | 268 action = new Action( |
| 272 "scoobydoo", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets"); | 269 "scoobydoo", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets"); |
| 273 action->mutable_args()->AppendString("vamoose"); | 270 action->mutable_args()->AppendString("vamoose"); |
| 274 action->set_page_url(GURL("http://www.google.com")); | 271 action->set_page_url(GURL("http://www.google.com")); |
| 275 policy->ProcessAction(action); | 272 policy->ProcessAction(action); |
| 276 | 273 |
| 277 CheckReadData( | 274 CheckReadData( |
| 278 policy, | 275 policy, |
| 279 "punky", | 276 "punky", |
| 280 0, | 277 0, |
| 281 base::Bind(&FullStreamUIPolicyTest::Arguments_GetTodaysActions)); | 278 base::Bind(&CountingPolicyTest::Arguments_GetTodaysActions)); |
| 282 policy->Close(); | 279 policy->Close(); |
| 283 } | 280 } |
| 284 | 281 |
| 285 // Check that we can read back less recent actions in the db. | 282 // Check that we can read back less recent actions in the db. |
| 286 TEST_F(FullStreamUIPolicyTest, GetOlderActions) { | 283 TEST_F(CountingPolicyTest, GetOlderActions) { |
| 287 ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get()); | 284 CountingPolicy* policy = new CountingPolicy(profile_.get()); |
| 285 policy->set_retention_time(base::TimeDelta::FromDays(14)); |
| 288 | 286 |
| 289 // Use a mock clock to ensure that events are not recorded on the wrong day | 287 // Use a mock clock to ensure that events are not recorded on the wrong day |
| 290 // when the test is run close to local midnight. | 288 // when the test is run close to local midnight. |
| 291 base::SimpleTestClock mock_clock; | 289 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); |
| 292 mock_clock.SetNow(base::Time::Now().LocalMidnight() + | 290 mock_clock->SetNow(base::Time::Now().LocalMidnight() + |
| 293 base::TimeDelta::FromHours(12)); | 291 base::TimeDelta::FromHours(12)); |
| 294 policy->SetClockForTesting(&mock_clock); | 292 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); |
| 295 | 293 |
| 296 // Record some actions | 294 // Record some actions |
| 297 scoped_refptr<Action> action = | 295 scoped_refptr<Action> action = |
| 298 new Action("punky", | 296 new Action("punky", |
| 299 mock_clock.Now() - base::TimeDelta::FromDays(3) - | 297 mock_clock->Now() - base::TimeDelta::FromDays(3) - |
| 300 base::TimeDelta::FromMinutes(40), | 298 base::TimeDelta::FromMinutes(40), |
| 301 Action::ACTION_API_CALL, | 299 Action::ACTION_API_CALL, |
| 302 "brewster"); | 300 "brewster"); |
| 303 action->mutable_args()->AppendString("woof"); | 301 action->mutable_args()->AppendString("woof"); |
| 304 policy->ProcessAction(action); | 302 policy->ProcessAction(action); |
| 305 | 303 |
| 306 action = new Action("punky", | 304 action = new Action("punky", |
| 307 mock_clock.Now() - base::TimeDelta::FromDays(3), | 305 mock_clock->Now() - base::TimeDelta::FromDays(3), |
| 308 Action::ACTION_DOM_ACCESS, | 306 Action::ACTION_DOM_ACCESS, |
| 309 "lets"); | 307 "lets"); |
| 310 action->mutable_args()->AppendString("vamoose"); | 308 action->mutable_args()->AppendString("vamoose"); |
| 311 action->set_page_url(GURL("http://www.google.com")); | 309 action->set_page_url(GURL("http://www.google.com")); |
| 312 policy->ProcessAction(action); | 310 policy->ProcessAction(action); |
| 313 | 311 |
| 314 action = new Action("punky", | 312 action = new Action("punky", |
| 315 mock_clock.Now(), | 313 mock_clock->Now(), |
| 316 Action::ACTION_DOM_ACCESS, | 314 Action::ACTION_DOM_ACCESS, |
| 317 "lets"); | 315 "lets"); |
| 318 action->mutable_args()->AppendString("too new"); | 316 action->mutable_args()->AppendString("too new"); |
| 319 action->set_page_url(GURL("http://www.google.com")); | 317 action->set_page_url(GURL("http://www.google.com")); |
| 320 policy->ProcessAction(action); | 318 policy->ProcessAction(action); |
| 321 | 319 |
| 322 action = new Action("punky", | 320 action = new Action("punky", |
| 323 mock_clock.Now() - base::TimeDelta::FromDays(7), | 321 mock_clock->Now() - base::TimeDelta::FromDays(7), |
| 324 Action::ACTION_DOM_ACCESS, | 322 Action::ACTION_DOM_ACCESS, |
| 325 "lets"); | 323 "lets"); |
| 326 action->mutable_args()->AppendString("too old"); | 324 action->mutable_args()->AppendString("too old"); |
| 327 action->set_page_url(GURL("http://www.google.com")); | 325 action->set_page_url(GURL("http://www.google.com")); |
| 328 policy->ProcessAction(action); | 326 policy->ProcessAction(action); |
| 329 | 327 |
| 330 CheckReadData( | 328 CheckReadData( |
| 331 policy, | 329 policy, |
| 332 "punky", | 330 "punky", |
| 333 3, | 331 3, |
| 334 base::Bind(&FullStreamUIPolicyTest::Arguments_GetOlderActions)); | 332 base::Bind(&CountingPolicyTest::Arguments_GetOlderActions)); |
| 333 |
| 335 policy->Close(); | 334 policy->Close(); |
| 336 } | 335 } |
| 337 | 336 |
| 337 // Check that merging of actions only occurs within the same day, not across |
| 338 // days, and that old data can be expired from the database. |
| 339 TEST_F(CountingPolicyTest, MergingAndExpiring) { |
| 340 CountingPolicy* policy = new CountingPolicy(profile_.get()); |
| 341 // Initially disable expiration by setting a retention time before any |
| 342 // actions we generate. |
| 343 policy->set_retention_time(base::TimeDelta::FromDays(14)); |
| 344 |
| 345 // Use a mock clock to ensure that events are not recorded on the wrong day |
| 346 // when the test is run close to local midnight. |
| 347 base::SimpleTestClock* mock_clock = new base::SimpleTestClock(); |
| 348 mock_clock->SetNow(base::Time::Now().LocalMidnight() + |
| 349 base::TimeDelta::FromHours(12)); |
| 350 policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock)); |
| 351 |
| 352 // The first two actions should be merged; the last one is on a separate day |
| 353 // and should not be. |
| 354 scoped_refptr<Action> action = |
| 355 new Action("punky", |
| 356 mock_clock->Now() - base::TimeDelta::FromDays(3) - |
| 357 base::TimeDelta::FromMinutes(40), |
| 358 Action::ACTION_API_CALL, |
| 359 "brewster"); |
| 360 policy->ProcessAction(action); |
| 361 |
| 362 action = new Action("punky", |
| 363 mock_clock->Now() - base::TimeDelta::FromDays(3) - |
| 364 base::TimeDelta::FromMinutes(20), |
| 365 Action::ACTION_API_CALL, |
| 366 "brewster"); |
| 367 policy->ProcessAction(action); |
| 368 |
| 369 action = new Action("punky", |
| 370 mock_clock->Now() - base::TimeDelta::FromDays(2) - |
| 371 base::TimeDelta::FromMinutes(20), |
| 372 Action::ACTION_API_CALL, |
| 373 "brewster"); |
| 374 policy->ProcessAction(action); |
| 375 |
| 376 CheckReadData(policy, |
| 377 "punky", |
| 378 3, |
| 379 base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 2)); |
| 380 CheckReadData(policy, |
| 381 "punky", |
| 382 2, |
| 383 base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 1)); |
| 384 |
| 385 // Clean actions before midnight two days ago. Force expiration to run by |
| 386 // clearing last_database_cleaning_time_ and submitting a new action. |
| 387 policy->set_retention_time(base::TimeDelta::FromDays(2)); |
| 388 policy->last_database_cleaning_time_ = base::Time(); |
| 389 action = new Action("punky", |
| 390 mock_clock->Now(), |
| 391 Action::ACTION_API_CALL, |
| 392 "brewster"); |
| 393 policy->ProcessAction(action); |
| 394 |
| 395 CheckReadData(policy, |
| 396 "punky", |
| 397 3, |
| 398 base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 0)); |
| 399 CheckReadData(policy, |
| 400 "punky", |
| 401 2, |
| 402 base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 1)); |
| 403 |
| 404 policy->Close(); |
| 405 } |
| 406 |
| 338 } // namespace extensions | 407 } // namespace extensions |
| OLD | NEW |