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