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