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 #ifndef CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_H_
6 #define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_H_
12 #include "base/callback.h"
13 #include "base/memory/singleton.h"
14 #include "base/observer_list_threadsafe.h"
15 #include "base/synchronization/lock.h"
16 #include "base/threading/thread.h"
17 #include "chrome/browser/extensions/activity_log/activity_actions.h"
18 #include "chrome/browser/extensions/activity_log/activity_database.h"
19 #include "chrome/browser/extensions/activity_log/activity_log_policy.h"
20 #include "chrome/browser/extensions/install_observer.h"
21 #include "chrome/browser/extensions/install_tracker.h"
22 #include "chrome/browser/extensions/tab_helper.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/common/extensions/dom_action_types.h"
25 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
26 #include "components/browser_context_keyed_service/browser_context_keyed_service.h"
27 #include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
30 using content::BrowserThread
;
32 namespace user_prefs
{
33 class PrefRegistrySyncable
;
36 namespace extensions
{
38 class ActivityLogPolicy
;
40 // A utility for tracing interesting activity for each extension.
41 // It writes to an ActivityDatabase on a separate thread to record the activity.
42 class ActivityLog
: public BrowserContextKeyedService
,
43 public TabHelper::ScriptExecutionObserver
,
44 public InstallObserver
{
46 // Observers can listen for activity events. There is probably only one
47 // observer: the activityLogPrivate API.
50 virtual void OnExtensionActivity(scoped_refptr
<Action
> activity
) = 0;
53 // ActivityLog is a singleton, so don't instantiate it with the constructor;
54 // use GetInstance instead.
55 static ActivityLog
* GetInstance(Profile
* profile
);
57 // Add/remove observer: the activityLogPrivate API only listens when the
58 // ActivityLog extension is registered for an event.
59 void AddObserver(Observer
* observer
);
60 void RemoveObserver(Observer
* observer
);
62 // Logs an extension action: passes it to any installed policy to be logged
63 // to the database, to any observers, and logs to the console if in testing
65 void LogAction(scoped_refptr
<Action
> action
);
67 // Gets all actions that match the specified fields. URLs are treated like
68 // prefixes; other fields are exact matches. Empty strings are not matched to
69 // anything. For daysAgo, today is 0, yesterday is 1, etc.; a negative number
70 // of days is treated as a missing parameter.
71 void GetFilteredActions(
72 const std::string
& extension_id
,
73 const Action::ActionType type
,
74 const std::string
& api_name
,
75 const std::string
& page_url
,
76 const std::string
& arg_url
,
79 <void(scoped_ptr
<std::vector
<scoped_refptr
<Action
> > >)>& callback
);
81 // Extension::InstallObserver
82 // We keep track of whether the whitelisted extension is installed; if it is,
83 // we want to recompute whether to have logging enabled.
84 virtual void OnExtensionInstalled(const Extension
* extension
) OVERRIDE
{}
85 virtual void OnExtensionLoaded(const Extension
* extension
) OVERRIDE
;
86 virtual void OnExtensionUnloaded(const Extension
* extension
) OVERRIDE
;
87 virtual void OnExtensionUninstalled(const Extension
* extension
) OVERRIDE
;
88 // We also have to list the following from InstallObserver.
89 virtual void OnBeginExtensionInstall(const std::string
& extension_id
,
90 const std::string
& extension_name
,
91 const gfx::ImageSkia
& installing_icon
,
93 bool is_platform_app
) OVERRIDE
{}
94 virtual void OnDownloadProgress(const std::string
& extension_id
,
95 int percent_downloaded
) OVERRIDE
{}
96 virtual void OnInstallFailure(const std::string
& extension_id
) OVERRIDE
{}
97 virtual void OnAppsReordered() OVERRIDE
{}
98 virtual void OnAppInstalledToAppList(
99 const std::string
& extension_id
) OVERRIDE
{}
100 virtual void OnShutdown() OVERRIDE
{}
102 // BrowserContextKeyedService
103 virtual void Shutdown() OVERRIDE
;
105 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable
* registry
);
107 // Clean up URLs from the activity log database.
108 // If restrict_urls is empty then all URLs in the activity log database are
109 // removed, otherwise only those in restrict_urls are removed.
110 void RemoveURLs(const std::vector
<GURL
>& restrict_urls
);
111 void RemoveURLs(const std::set
<GURL
>& restrict_urls
);
112 void RemoveURL(const GURL
& url
);
114 // Deletes the database associated with the policy that's currently in use.
115 void DeleteDatabase();
118 friend class ActivityLogFactory
;
119 friend class ActivityLogTest
;
120 friend class RenderViewActivityLogTest
;
122 explicit ActivityLog(Profile
* profile
);
123 virtual ~ActivityLog();
125 // Specifies if the Watchdog app is active (installed & enabled).
126 // If so, we need to log to the database and stream to the API.
127 bool IsWatchdogAppActive();
128 // If we're in a browser test, we need to pretend that the watchdog app is
130 void SetWatchdogAppActive(bool active
);
132 // Specifies if we need to record actions to the db. If so, we need to log to
133 // the database. This is true if the Watchdog app is active *or* the
134 // --enable-extension-activity-logging flag is set.
135 bool IsDatabaseEnabled();
137 // Delayed initialization of Install Tracker which waits until after the
138 // ExtensionSystem/ExtensionService are done with their own setup.
139 void InitInstallTracker();
141 // TabHelper::ScriptExecutionObserver implementation.
142 // Fires when a ContentScript is executed.
143 virtual void OnScriptsExecuted(
144 const content::WebContents
* web_contents
,
145 const ExecutingScriptsMap
& extension_ids
,
147 const GURL
& on_url
) OVERRIDE
;
149 // At the moment, ActivityLog will use only one policy for summarization.
150 // These methods are used to choose and set the most appropriate policy.
151 // Changing policies at runtime is not recommended, and likely only should be
152 // done for unit tests.
153 void ChooseDatabasePolicy();
154 void SetDatabasePolicy(ActivityLogPolicy::PolicyType policy_type
);
156 typedef ObserverListThreadSafe
<Observer
> ObserverList
;
157 scoped_refptr
<ObserverList
> observers_
;
159 // Policy objects are owned by the ActivityLog, but cannot be scoped_ptrs
160 // since they may need to do some cleanup work on the database thread.
161 // Calling policy->Close() will free the object; see the comments on the
162 // ActivityDatabase class for full details.
164 // The database policy object takes care of recording & looking up data:
165 // data summarization, compression, and logging. There should only be a
166 // database_policy_ if the Watchdog app is installed or flag is set.
167 ActivityLogDatabasePolicy
* database_policy_
;
168 ActivityLogPolicy::PolicyType database_policy_type_
;
170 // The UMA policy is used for recording statistics about extension behavior.
171 // This policy is always in use, except for Incognito profiles.
172 ActivityLogPolicy
* uma_policy_
;
175 bool db_enabled_
; // Whether logging to disk is currently enabled.
176 // testing_mode_ controls which policy is selected.
177 // * By default, we choose a policy that doesn't log most arguments to avoid
178 // saving too much data. We also elide some arguments for privacy reasons.
179 // * In testing mode, we choose a policy that logs all arguments.
180 // testing_mode_ also causes us to print to the console.
182 // We need the DB, FILE, and IO threads to write to the database.
183 // In some cases (tests), these threads might not exist, so we avoid
184 // dispatching anything to the policies/database to prevent things from
188 // Used to track whether the whitelisted extension is installed. If it's
189 // added or removed, enabled_ may change.
190 InstallTracker
* tracker_
;
192 // Set if the watchdog app is installed and enabled. Maintained by
193 // kWatchdogExtensionActive pref variable.
194 bool watchdog_app_active_
;
196 FRIEND_TEST_ALL_PREFIXES(ActivityLogApiTest
, TriggerEvent
);
197 FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest
, AppAndCommandLine
);
198 FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest
, CommandLineSwitch
);
199 FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest
, NoSwitch
);
200 FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest
, PrefSwitch
);
201 FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest
, WatchdogSwitch
);
202 DISALLOW_COPY_AND_ASSIGN(ActivityLog
);
205 // Each profile has different extensions, so we keep a different database for
207 class ActivityLogFactory
: public BrowserContextKeyedServiceFactory
{
209 static ActivityLog
* GetForProfile(Profile
* profile
) {
210 return static_cast<ActivityLog
*>(
211 GetInstance()->GetServiceForBrowserContext(profile
, true));
214 static ActivityLogFactory
* GetInstance();
217 friend struct DefaultSingletonTraits
<ActivityLogFactory
>;
218 ActivityLogFactory();
219 virtual ~ActivityLogFactory();
221 virtual BrowserContextKeyedService
* BuildServiceInstanceFor(
222 content::BrowserContext
* profile
) const OVERRIDE
;
224 virtual content::BrowserContext
* GetBrowserContextToUse(
225 content::BrowserContext
* context
) const OVERRIDE
;
227 DISALLOW_COPY_AND_ASSIGN(ActivityLogFactory
);
231 } // namespace extensions
233 #endif // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_H_