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 #ifndef CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_H_ 6 #define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_H_ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 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" 28 #include "extensions/browser/event_router.h" 29 30 class Profile; 31 using content::BrowserThread; 32 33 namespace content { 34 class BrowserContext; 35 } 36 37 namespace user_prefs { 38 class PrefRegistrySyncable; 39 } 40 41 namespace extensions { 42 class Extension; 43 class ActivityLogPolicy; 44 45 // A utility for tracing interesting activity for each extension. 46 // It writes to an ActivityDatabase on a separate thread to record the activity. 47 class ActivityLog : public BrowserContextKeyedService, 48 public EventRouter::EventDispatchObserver, 49 public TabHelper::ScriptExecutionObserver, 50 public InstallObserver { 51 public: 52 // Observers can listen for activity events. There is probably only one 53 // observer: the activityLogPrivate API. 54 class Observer { 55 public: 56 virtual void OnExtensionActivity(scoped_refptr<Action> activity) = 0; 57 }; 58 59 // ActivityLog is a singleton, so don't instantiate it with the constructor; 60 // use GetInstance instead. 61 static ActivityLog* GetInstance(content::BrowserContext* context); 62 63 // Add/remove observer: the activityLogPrivate API only listens when the 64 // ActivityLog extension is registered for an event. 65 void AddObserver(Observer* observer); 66 void RemoveObserver(Observer* observer); 67 68 // Logs an extension action: passes it to any installed policy to be logged 69 // to the database, to any observers, and logs to the console if in testing 70 // mode. 71 void LogAction(scoped_refptr<Action> action); 72 73 // Gets all actions that match the specified fields. URLs are treated like 74 // prefixes; other fields are exact matches. Empty strings are not matched to 75 // anything. For daysAgo, today is 0, yesterday is 1, etc.; a negative number 76 // of days is treated as a missing parameter. 77 void GetFilteredActions( 78 const std::string& extension_id, 79 const Action::ActionType type, 80 const std::string& api_name, 81 const std::string& page_url, 82 const std::string& arg_url, 83 const int days_ago, 84 const base::Callback 85 <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback); 86 87 // Extension::InstallObserver 88 // We keep track of whether the whitelisted extension is installed; if it is, 89 // we want to recompute whether to have logging enabled. 90 virtual void OnExtensionInstalled(const Extension* extension) OVERRIDE {} 91 virtual void OnExtensionLoaded(const Extension* extension) OVERRIDE; 92 virtual void OnExtensionUnloaded(const Extension* extension) OVERRIDE; 93 virtual void OnExtensionUninstalled(const Extension* extension) OVERRIDE; 94 // We also have to list the following from InstallObserver. 95 virtual void OnBeginExtensionInstall( 96 const ExtensionInstallParams& params) OVERRIDE {} 97 virtual void OnDownloadProgress(const std::string& extension_id, 98 int percent_downloaded) OVERRIDE {} 99 virtual void OnInstallFailure(const std::string& extension_id) OVERRIDE {} 100 virtual void OnAppsReordered() OVERRIDE {} 101 virtual void OnAppInstalledToAppList( 102 const std::string& extension_id) OVERRIDE {} 103 virtual void OnShutdown() OVERRIDE {} 104 105 // EventRouter::EventDispatchObserver 106 virtual void OnWillDispatchEvent(scoped_ptr<EventDispatchInfo> details) 107 OVERRIDE; 108 109 // BrowserContextKeyedService 110 virtual void Shutdown() OVERRIDE; 111 112 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); 113 114 // Clean up URLs from the activity log database. 115 // If restrict_urls is empty then all URLs in the activity log database are 116 // removed, otherwise only those in restrict_urls are removed. 117 void RemoveURLs(const std::vector<GURL>& restrict_urls); 118 void RemoveURLs(const std::set<GURL>& restrict_urls); 119 void RemoveURL(const GURL& url); 120 121 // Deletes the database associated with the policy that's currently in use. 122 void DeleteDatabase(); 123 124 private: 125 friend class ActivityLogFactory; 126 friend class ActivityLogTest; 127 friend class RenderViewActivityLogTest; 128 129 explicit ActivityLog(Profile* profile); 130 virtual ~ActivityLog(); 131 132 // Specifies if the Watchdog app is active (installed & enabled). 133 // If so, we need to log to the database and stream to the API. 134 bool IsWatchdogAppActive(); 135 // If we're in a browser test, we need to pretend that the watchdog app is 136 // active. 137 void SetWatchdogAppActive(bool active); 138 139 // Specifies if we need to record actions to the db. If so, we need to log to 140 // the database. This is true if the Watchdog app is active *or* the 141 // --enable-extension-activity-logging flag is set. 142 bool IsDatabaseEnabled(); 143 144 // Delayed initialization of Install Tracker which waits until after the 145 // ExtensionSystem/ExtensionService are done with their own setup. 146 void InitInstallTracker(); 147 148 // TabHelper::ScriptExecutionObserver implementation. 149 // Fires when a ContentScript is executed. 150 virtual void OnScriptsExecuted( 151 const content::WebContents* web_contents, 152 const ExecutingScriptsMap& extension_ids, 153 int32 page_id, 154 const GURL& on_url) OVERRIDE; 155 156 // At the moment, ActivityLog will use only one policy for summarization. 157 // These methods are used to choose and set the most appropriate policy. 158 // Changing policies at runtime is not recommended, and likely only should be 159 // done for unit tests. 160 void ChooseDatabasePolicy(); 161 void SetDatabasePolicy(ActivityLogPolicy::PolicyType policy_type); 162 163 typedef ObserverListThreadSafe<Observer> ObserverList; 164 scoped_refptr<ObserverList> observers_; 165 166 // Policy objects are owned by the ActivityLog, but cannot be scoped_ptrs 167 // since they may need to do some cleanup work on the database thread. 168 // Calling policy->Close() will free the object; see the comments on the 169 // ActivityDatabase class for full details. 170 171 // The database policy object takes care of recording & looking up data: 172 // data summarization, compression, and logging. There should only be a 173 // database_policy_ if the Watchdog app is installed or flag is set. 174 ActivityLogDatabasePolicy* database_policy_; 175 ActivityLogPolicy::PolicyType database_policy_type_; 176 177 // The UMA policy is used for recording statistics about extension behavior. 178 // This policy is always in use, except for Incognito profiles. 179 ActivityLogPolicy* uma_policy_; 180 181 Profile* profile_; 182 bool db_enabled_; // Whether logging to disk is currently enabled. 183 // testing_mode_ controls which policy is selected. 184 // * By default, we choose a policy that doesn't log most arguments to avoid 185 // saving too much data. We also elide some arguments for privacy reasons. 186 // * In testing mode, we choose a policy that logs all arguments. 187 // testing_mode_ also causes us to print to the console. 188 bool testing_mode_; 189 // We need the DB, FILE, and IO threads to write to the database. 190 // In some cases (tests), these threads might not exist, so we avoid 191 // dispatching anything to the policies/database to prevent things from 192 // exploding. 193 bool has_threads_; 194 195 // Used to track whether the whitelisted extension is installed. If it's 196 // added or removed, enabled_ may change. 197 InstallTracker* tracker_; 198 199 // Set if the watchdog app is installed and enabled. Maintained by 200 // kWatchdogExtensionActive pref variable. Since there are multiple valid 201 // extension IDs, this needs to be an int to count how many are installed. 202 int watchdog_apps_active_; 203 204 FRIEND_TEST_ALL_PREFIXES(ActivityLogApiTest, TriggerEvent); 205 FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest, AppAndCommandLine); 206 FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest, CommandLineSwitch); 207 FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest, NoSwitch); 208 FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest, PrefSwitch); 209 FRIEND_TEST_ALL_PREFIXES(ActivityLogEnabledTest, WatchdogSwitch); 210 DISALLOW_COPY_AND_ASSIGN(ActivityLog); 211 }; 212 213 // Each profile has different extensions, so we keep a different database for 214 // each profile. 215 class ActivityLogFactory : public BrowserContextKeyedServiceFactory { 216 public: 217 static ActivityLog* GetForBrowserContext(content::BrowserContext* context) { 218 return static_cast<ActivityLog*>( 219 GetInstance()->GetServiceForBrowserContext(context, true)); 220 } 221 222 static ActivityLogFactory* GetInstance(); 223 224 private: 225 friend struct DefaultSingletonTraits<ActivityLogFactory>; 226 ActivityLogFactory(); 227 virtual ~ActivityLogFactory(); 228 229 virtual BrowserContextKeyedService* BuildServiceInstanceFor( 230 content::BrowserContext* profile) const OVERRIDE; 231 232 virtual content::BrowserContext* GetBrowserContextToUse( 233 content::BrowserContext* context) const OVERRIDE; 234 235 DISALLOW_COPY_AND_ASSIGN(ActivityLogFactory); 236 }; 237 238 239 } // namespace extensions 240 241 #endif // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_H_ 242