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