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