Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / activity_log / activity_log_unittest.cc
blob72fa22c4d5c8505c29d986ae4e8118aac277dfdd
1 // Copyright (c) 2012 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.
5 #include "base/command_line.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/run_loop.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "chrome/browser/extensions/activity_log/activity_action_constants.h"
11 #include "chrome/browser/extensions/activity_log/activity_log.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/test_extension_system.h"
14 #include "chrome/browser/prerender/prerender_handle.h"
15 #include "chrome/browser/prerender/prerender_manager.h"
16 #include "chrome/browser/prerender/prerender_manager_factory.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/browser/web_contents.h"
22 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "extensions/browser/extension_registry.h"
24 #include "extensions/browser/uninstall_reason.h"
25 #include "extensions/common/dom_action_types.h"
26 #include "extensions/common/extension_builder.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 #if defined(OS_CHROMEOS)
30 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
31 #include "chrome/browser/chromeos/settings/cros_settings.h"
32 #include "chrome/browser/chromeos/settings/device_settings_service.h"
33 #endif
35 namespace {
37 const char kExtensionId[] = "abc";
39 const char* const kUrlApiCalls[] = {
40 "HTMLButtonElement.formAction", "HTMLEmbedElement.src",
41 "HTMLFormElement.action", "HTMLFrameElement.src",
42 "HTMLHtmlElement.manifest", "HTMLIFrameElement.src",
43 "HTMLImageElement.longDesc", "HTMLImageElement.src",
44 "HTMLImageElement.lowsrc", "HTMLInputElement.formAction",
45 "HTMLInputElement.src", "HTMLLinkElement.href",
46 "HTMLMediaElement.src", "HTMLMediaElement.currentSrc",
47 "HTMLModElement.cite", "HTMLObjectElement.data",
48 "HTMLQuoteElement.cite", "HTMLScriptElement.src",
49 "HTMLSourceElement.src", "HTMLTrackElement.src",
50 "HTMLVideoElement.poster"};
52 } // namespace
54 namespace extensions {
56 class ActivityLogTest : public ChromeRenderViewHostTestHarness {
57 protected:
58 void SetUp() override {
59 ChromeRenderViewHostTestHarness::SetUp();
60 #if defined OS_CHROMEOS
61 test_user_manager_.reset(new chromeos::ScopedTestUserManager());
62 #endif
63 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
64 base::CommandLine::ForCurrentProcess()->AppendSwitch(
65 switches::kEnableExtensionActivityLogging);
66 base::CommandLine::ForCurrentProcess()->AppendSwitch(
67 switches::kEnableExtensionActivityLogTesting);
68 extension_service_ = static_cast<TestExtensionSystem*>(
69 ExtensionSystem::Get(profile()))->CreateExtensionService
70 (&command_line, base::FilePath(), false);
71 base::RunLoop().RunUntilIdle();
74 void TearDown() override {
75 #if defined OS_CHROMEOS
76 test_user_manager_.reset();
77 #endif
78 base::RunLoop().RunUntilIdle();
79 ChromeRenderViewHostTestHarness::TearDown();
82 static void RetrieveActions_LogAndFetchActions0(
83 scoped_ptr<std::vector<scoped_refptr<Action> > > i) {
84 ASSERT_EQ(0, static_cast<int>(i->size()));
87 static void RetrieveActions_LogAndFetchActions2(
88 scoped_ptr<std::vector<scoped_refptr<Action> > > i) {
89 ASSERT_EQ(2, static_cast<int>(i->size()));
92 void SetPolicy(bool log_arguments) {
93 ActivityLog* activity_log = ActivityLog::GetInstance(profile());
94 if (log_arguments)
95 activity_log->SetDatabasePolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
96 else
97 activity_log->SetDatabasePolicy(ActivityLogPolicy::POLICY_COUNTS);
100 bool GetDatabaseEnabled() {
101 ActivityLog* activity_log = ActivityLog::GetInstance(profile());
102 return activity_log->IsDatabaseEnabled();
105 bool GetWatchdogActive() {
106 ActivityLog* activity_log = ActivityLog::GetInstance(profile());
107 return activity_log->IsWatchdogAppActive();
110 static void Arguments_Prerender(
111 scoped_ptr<std::vector<scoped_refptr<Action> > > i) {
112 ASSERT_EQ(1U, i->size());
113 scoped_refptr<Action> last = i->front();
115 ASSERT_EQ("odlameecjipmbmbejkplpemijjgpljce", last->extension_id());
116 ASSERT_EQ(Action::ACTION_CONTENT_SCRIPT, last->action_type());
117 ASSERT_EQ("[\"script\"]",
118 ActivityLogPolicy::Util::Serialize(last->args()));
119 ASSERT_EQ("http://www.google.com/", last->SerializePageUrl());
120 ASSERT_EQ("{\"prerender\":true}",
121 ActivityLogPolicy::Util::Serialize(last->other()));
122 ASSERT_EQ("", last->api_name());
123 ASSERT_EQ("", last->page_title());
124 ASSERT_EQ("", last->SerializeArgUrl());
127 static void RetrieveActions_ArgUrlExtraction(
128 scoped_ptr<std::vector<scoped_refptr<Action> > > i) {
129 const base::DictionaryValue* other = NULL;
130 int dom_verb = -1;
132 ASSERT_EQ(4U, i->size());
133 scoped_refptr<Action> action = i->at(0);
134 ASSERT_EQ("XMLHttpRequest.open", action->api_name());
135 ASSERT_EQ("[\"POST\",\"\\u003Carg_url>\"]",
136 ActivityLogPolicy::Util::Serialize(action->args()));
137 ASSERT_EQ("http://api.google.com/", action->arg_url().spec());
138 // Test that the dom_verb field was changed to XHR (from METHOD). This
139 // could be tested on all retrieved XHR actions but it would be redundant,
140 // so just test once.
141 other = action->other();
142 ASSERT_TRUE(other);
143 ASSERT_TRUE(other->GetInteger(activity_log_constants::kActionDomVerb,
144 &dom_verb));
145 ASSERT_EQ(DomActionType::XHR, dom_verb);
147 action = i->at(1);
148 ASSERT_EQ("XMLHttpRequest.open", action->api_name());
149 ASSERT_EQ("[\"POST\",\"\\u003Carg_url>\"]",
150 ActivityLogPolicy::Util::Serialize(action->args()));
151 ASSERT_EQ("http://www.google.com/api/", action->arg_url().spec());
153 action = i->at(2);
154 ASSERT_EQ("XMLHttpRequest.open", action->api_name());
155 ASSERT_EQ("[\"POST\",\"/api/\"]",
156 ActivityLogPolicy::Util::Serialize(action->args()));
157 ASSERT_FALSE(action->arg_url().is_valid());
159 action = i->at(3);
160 ASSERT_EQ("windows.create", action->api_name());
161 ASSERT_EQ("[{\"url\":\"\\u003Carg_url>\"}]",
162 ActivityLogPolicy::Util::Serialize(action->args()));
163 ASSERT_EQ("http://www.google.co.uk/", action->arg_url().spec());
166 static void RetrieveActions_ArgUrlApiCalls(
167 scoped_ptr<std::vector<scoped_refptr<Action> > > actions) {
168 size_t api_calls_size = arraysize(kUrlApiCalls);
169 const base::DictionaryValue* other = NULL;
170 int dom_verb = -1;
172 ASSERT_EQ(api_calls_size, actions->size());
174 for (size_t i = 0; i < actions->size(); i++) {
175 scoped_refptr<Action> action = actions->at(i);
176 ASSERT_EQ(kExtensionId, action->extension_id());
177 ASSERT_EQ(Action::ACTION_DOM_ACCESS, action->action_type());
178 ASSERT_EQ(kUrlApiCalls[i], action->api_name());
179 ASSERT_EQ("[\"\\u003Carg_url>\"]",
180 ActivityLogPolicy::Util::Serialize(action->args()));
181 ASSERT_EQ("http://www.google.co.uk/", action->arg_url().spec());
182 other = action->other();
183 ASSERT_TRUE(other);
184 ASSERT_TRUE(
185 other->GetInteger(activity_log_constants::kActionDomVerb, &dom_verb));
186 ASSERT_EQ(DomActionType::SETTER, dom_verb);
190 ExtensionService* extension_service_;
192 #if defined OS_CHROMEOS
193 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
194 chromeos::ScopedTestCrosSettings test_cros_settings_;
195 scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
196 #endif
199 TEST_F(ActivityLogTest, Construct) {
200 ASSERT_TRUE(GetDatabaseEnabled());
201 ASSERT_FALSE(GetWatchdogActive());
204 TEST_F(ActivityLogTest, LogAndFetchActions) {
205 ActivityLog* activity_log = ActivityLog::GetInstance(profile());
206 scoped_ptr<base::ListValue> args(new base::ListValue());
207 ASSERT_TRUE(GetDatabaseEnabled());
209 // Write some API calls
210 scoped_refptr<Action> action = new Action(kExtensionId,
211 base::Time::Now(),
212 Action::ACTION_API_CALL,
213 "tabs.testMethod");
214 activity_log->LogAction(action);
215 action = new Action(kExtensionId,
216 base::Time::Now(),
217 Action::ACTION_DOM_ACCESS,
218 "document.write");
219 action->set_page_url(GURL("http://www.google.com"));
220 activity_log->LogAction(action);
222 activity_log->GetFilteredActions(
223 kExtensionId,
224 Action::ACTION_ANY,
229 base::Bind(ActivityLogTest::RetrieveActions_LogAndFetchActions2));
232 TEST_F(ActivityLogTest, LogPrerender) {
233 scoped_refptr<const Extension> extension =
234 ExtensionBuilder()
235 .SetManifest(DictionaryBuilder()
236 .Set("name", "Test extension")
237 .Set("version", "1.0.0")
238 .Set("manifest_version", 2))
239 .Build();
240 extension_service_->AddExtension(extension.get());
241 ActivityLog* activity_log = ActivityLog::GetInstance(profile());
242 ASSERT_TRUE(GetDatabaseEnabled());
243 GURL url("http://www.google.com");
245 prerender::PrerenderManager* prerender_manager =
246 prerender::PrerenderManagerFactory::GetForProfile(
247 Profile::FromBrowserContext(profile()));
249 const gfx::Size kSize(640, 480);
250 scoped_ptr<prerender::PrerenderHandle> prerender_handle(
251 prerender_manager->AddPrerenderFromOmnibox(
252 url,
253 web_contents()->GetController().GetDefaultSessionStorageNamespace(),
254 kSize));
256 const std::vector<content::WebContents*> contentses =
257 prerender_manager->GetAllPrerenderingContents();
258 ASSERT_EQ(1U, contentses.size());
259 content::WebContents *contents = contentses[0];
260 ASSERT_TRUE(prerender_manager->IsWebContentsPrerendering(contents, NULL));
262 ScriptExecutionObserver::ExecutingScriptsMap executing_scripts;
263 executing_scripts[extension->id()].insert("script");
265 static_cast<ScriptExecutionObserver*>(activity_log)
266 ->OnScriptsExecuted(contents, executing_scripts, url);
268 activity_log->GetFilteredActions(
269 extension->id(),
270 Action::ACTION_ANY,
275 base::Bind(ActivityLogTest::Arguments_Prerender));
277 prerender_manager->CancelAllPrerenders();
280 TEST_F(ActivityLogTest, ArgUrlExtraction) {
281 ActivityLog* activity_log = ActivityLog::GetInstance(profile());
282 scoped_ptr<base::ListValue> args(new base::ListValue());
284 base::Time now = base::Time::Now();
286 // Submit a DOM API call which should have its URL extracted into the arg_url
287 // field.
288 scoped_refptr<Action> action = new Action(kExtensionId,
289 now,
290 Action::ACTION_DOM_ACCESS,
291 "XMLHttpRequest.open");
292 action->set_page_url(GURL("http://www.google.com/"));
293 action->mutable_args()->AppendString("POST");
294 action->mutable_args()->AppendString("http://api.google.com/");
295 action->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
296 DomActionType::METHOD);
297 activity_log->LogAction(action);
299 // Submit a DOM API call with a relative URL in the argument, which should be
300 // resolved relative to the page URL.
301 action = new Action(kExtensionId,
302 now - base::TimeDelta::FromSeconds(1),
303 Action::ACTION_DOM_ACCESS,
304 "XMLHttpRequest.open");
305 action->set_page_url(GURL("http://www.google.com/"));
306 action->mutable_args()->AppendString("POST");
307 action->mutable_args()->AppendString("/api/");
308 action->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
309 DomActionType::METHOD);
310 activity_log->LogAction(action);
312 // Submit a DOM API call with a relative URL but no base page URL against
313 // which to resolve.
314 action = new Action(kExtensionId,
315 now - base::TimeDelta::FromSeconds(2),
316 Action::ACTION_DOM_ACCESS,
317 "XMLHttpRequest.open");
318 action->mutable_args()->AppendString("POST");
319 action->mutable_args()->AppendString("/api/");
320 action->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
321 DomActionType::METHOD);
322 activity_log->LogAction(action);
324 // Submit an API call with an embedded URL.
325 action = new Action(kExtensionId,
326 now - base::TimeDelta::FromSeconds(3),
327 Action::ACTION_API_CALL,
328 "windows.create");
329 action->set_args(
330 ListBuilder()
331 .Append(DictionaryBuilder().Set("url", "http://www.google.co.uk"))
332 .Build());
333 activity_log->LogAction(action);
335 activity_log->GetFilteredActions(
336 kExtensionId,
337 Action::ACTION_ANY,
342 base::Bind(ActivityLogTest::RetrieveActions_ArgUrlExtraction));
345 TEST_F(ActivityLogTest, UninstalledExtension) {
346 scoped_refptr<const Extension> extension =
347 ExtensionBuilder()
348 .SetManifest(DictionaryBuilder()
349 .Set("name", "Test extension")
350 .Set("version", "1.0.0")
351 .Set("manifest_version", 2))
352 .Build();
354 ActivityLog* activity_log = ActivityLog::GetInstance(profile());
355 scoped_ptr<base::ListValue> args(new base::ListValue());
356 ASSERT_TRUE(GetDatabaseEnabled());
358 // Write some API calls
359 scoped_refptr<Action> action = new Action(extension->id(),
360 base::Time::Now(),
361 Action::ACTION_API_CALL,
362 "tabs.testMethod");
363 activity_log->LogAction(action);
364 action = new Action(extension->id(),
365 base::Time::Now(),
366 Action::ACTION_DOM_ACCESS,
367 "document.write");
368 action->set_page_url(GURL("http://www.google.com"));
370 activity_log->OnExtensionUninstalled(
371 NULL, extension.get(), extensions::UNINSTALL_REASON_FOR_TESTING);
372 activity_log->GetFilteredActions(
373 extension->id(),
374 Action::ACTION_ANY,
379 base::Bind(ActivityLogTest::RetrieveActions_LogAndFetchActions0));
382 TEST_F(ActivityLogTest, ArgUrlApiCalls) {
383 ActivityLog* activity_log = ActivityLog::GetInstance(profile());
384 scoped_ptr<base::ListValue> args(new base::ListValue());
385 base::Time now = base::Time::Now();
386 int api_calls_size = arraysize(kUrlApiCalls);
387 scoped_refptr<Action> action;
389 for (int i = 0; i < api_calls_size; i++) {
390 action = new Action(kExtensionId,
391 now - base::TimeDelta::FromSeconds(i),
392 Action::ACTION_DOM_ACCESS,
393 kUrlApiCalls[i]);
394 action->mutable_args()->AppendString("http://www.google.co.uk");
395 action->mutable_other()->SetInteger(activity_log_constants::kActionDomVerb,
396 DomActionType::SETTER);
397 activity_log->LogAction(action);
400 activity_log->GetFilteredActions(
401 kExtensionId,
402 Action::ACTION_ANY,
407 base::Bind(ActivityLogTest::RetrieveActions_ArgUrlApiCalls));
410 } // namespace extensions